磁带的最优存储问题(贪心选择)


题目描述

设有n 个程序{1,2,…, n }要存放在长度为L的磁带上。程序i存放在磁带上的长度是Li, 1<= i<= n。这n 个程序的读取概率分别是p1,p2,...,pn,且pi+p2+...+pn = 1。如果将这n 个程序按 i1,i2,....,in 的次序存放,则读取程序ir 所需的时间tr=c*(Pi1*Li2+Pi2*Li2+...+Pir*Lir)。这n 个程序的平均读取 时间为t1+t2+...+tn。 磁带最优存储问题要求确定这n 个程序在磁带上的一个存储次序,使平均读取时间达到 最小。试设计一个解此问题的算法,并分析算法的正确性和计算复杂性。 编程任务: 对于给定的n个程序存放在磁带上的长度和读取概率,编程计算n个程序的最优存储方 案。

输入
由文件input.txt给出输入数据。第一行是正整数n,表示文件个数。接下来的n行中, 
每行有2 个正整数a 和b,分别表示程序存放在磁带上的长度和读取概率。实际上第k个程 
序的读取概率ak/(a1+a2+...+an)。对所有输入均假定c=1。

输出

输出一个实数,保留1位小数,表示计算出的最小平均读取时间。

示例输入

5
71     872
46     452
9       265
73     120
35      87

示例输出

85.6


算法设计
n个程序的平均读取时间:(贪心策略)
 在该题目中,要考虑综合因素:长度和读取概率。要求n个程序的平均读取时间最短。按照贪心策略,则每个程序的读取时间都应该最短。故:
(1)计算每个程序的长度和读取概率的乘积。
(2)对(1)产生的结果进行排序。
(3)当访问次序确定时,求出每个程序的访问时间。
(4)求出n个程序的平均读取时间。
程序源代码如下
/* 
  length[n]   程序长度
  length1[n]  每个程序的长度和概率的乘积
  gailv[n]    程序的概率
  gailv1[n]   程序计算后的概率
  sum[n]      读取每个程序所需的时间
*/
# include<stdio.h>
# include<stdlib.h>
# define N 10
//计算每个文件被读取的概率
int calculate(int n,int gailv[n],double gailv1[n])
{
     int sum=0;
     int i;
     for(i=0;i<n;i++)
     {
          sum+=gailv[i];
     }
     for(i=0;i<n;i++)
     {
          gailv1[i]=(double)gailv[i]/sum;
     }
     return 0;
}
//计算文件和读取概率的乘积
int multiple(int n,double gailv1[n],int length[n],double length1[n])
{
     int i;
     for(i=0;i<n;i++)
     {
          length1[i]=((double)gailv1[i])*((double)length[i]);
     }
     return 0;
}
//对乘积进行排序
int swap(int n,double length1[n])
{
      int i,j;
      for(i=0;i<n;i++)
      {
          for(j=i+1;j<n;j++)
          {
              if(length1[i]>length1[j])
              {
                   double temp;
                   temp=length1[i];
                   length1[i]=length1[j];
                   length1[j]=temp;
              }
          }
      }
      return 0;
}
//读取每个程序所用的时间
int he(int n,double length1[n],double sum[n])
{
     int i;
     for(i=0;i<n;i++)
     {
          double t;
          t+=length1[i];
          sum[i]=t;
     }
     return 0;
}
//读取所有程序的平均时间
int Min_time(int n,double sum[n])
{
     int i;
     double min_time=0.0;
     for(i=0;i<n;i++)
     {
         min_time+=sum[i];
     }
     printf("最小平均读取时间为:\n");
     printf("%f\n",min_time);
     return 0;
}


int main()
{
     int n,i;
     int length[N];
     int gailv[N];
     double gailv1[N];
     double length1[N];
     double sum[N];
     printf("请输入文件的个数:\n");
     scanf("%d",&n);
     printf("请输入每个文件的长度:\n");
     for(i=0;i<n;i++)
     {
          scanf("%d",&length[i]);
     }
     printf("请输入每个文件的概率:\n");
     for(i=0;i<n;i++)
     {
          scanf("%d",&gailv[i]);
     }
     calculate(n,gailv,gailv1);
     multiple(n,gailv1,length,length1);
     swap(n,length1);
     he(n,length1,sum);
     Min_time(n,sum);

     return 0;
}
程序的运行结果:








  • 9
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值